package com.heima.wemedia.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.heima.article.client.ArticleFeign;
import com.heima.common.aliyun.GreenImageUploadScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.delayTask.RedisDelayedQueueUtil;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.util.BeanHelper;
import com.heima.common.util.JsonUtils;
import com.heima.common.util.SensitiveWordUtil;
import com.heima.file.service.MinioService;
import com.heima.model.media.dtos.WmNewsResultDTO;
import com.heima.wemedia.entity.WmNews;
import com.heima.wemedia.entity.WmSensitive;
import com.heima.wemedia.service.WmNewsAuditService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmSensitiveService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class WmNewsAuditServiceImpl implements WmNewsAuditService {

    @Autowired
    private WmNewsService wmNewsService;
    @Autowired
    private RedisDelayedQueueUtil delayedQueueUtil;
    /**
     * 自媒体文章审核
     * @param wmNews
     */
    @Override
    @Async  //当前方法是一个异步执行的方法
    public void auditNews(WmNews wmNews) {
//        只处理status是   1-待审核  的文章
        if(wmNews.getStatus() != 1){
            log.info("文章状态不是待审核，无法操作，返回");
            return;
        }
//        分析文章，获取文章的所有文本内容、图片路径
        Map<String,Object> map = handlerGetTextAndImageUrl(wmNews);
//        获取所有文本内容
        String text = map.get("text").toString();
//        获取所有图片路径
        Set<String> imageUrls = (Set<String>)map.get("image");
//        检查敏感词
        boolean b2 = handlerSensitiveScan(text,wmNews.getId());
        if(!b2){
            log.error("敏感词检测不通过");
            throw new LeadException(AppHttpCodeEnum.TEXT_ILLEGAL);
        }
//        调用阿里云的文本审核接口,传所有文本内容
        boolean b  = handlerAliyunTextScan(text,wmNews.getId());
        if(!b){
            log.error("阿里云文本审核 不通过");
            throw new LeadException(AppHttpCodeEnum.TEXT_ILLEGAL);
        }
//        调用阿里云的图片审核接口,传所有图片的路径
        if(!CollectionUtils.isEmpty(imageUrls)){
            boolean b1 = handlerAliyunImageScan(imageUrls,wmNews.getId());
            if(!b1){
                log.error("阿里云图片审核 不通过");
                throw new LeadException(AppHttpCodeEnum.PARAM_IMAGE_ILLEGAL);
            }
        }
//        修改自媒体文章状态   8- 审核通过
        updateWmNewsStatus(wmNews.getId(),8,null,null);
//        当有发布时间，并且发布时间大于当前时间， 直接返回
        if(wmNews.getPublishTime() != null &&
            wmNews.getPublishTime().getTime() > System.currentTimeMillis()){
            log.info("没有到发布时间，需要放入延迟队列，newsId={},publishTime={}",wmNews.getId(),wmNews.getPublishTime());
//              计算延迟的时间
            long time = wmNews.getPublishTime().getTime() - System.currentTimeMillis();
//            需要放入延迟队列
            delayedQueueUtil.addQueue(wmNews.getId(),time, TimeUnit.MILLISECONDS,"wm.news.pub");
            return ;
        }
//        远程调用article服务，保存article文章
        pubWmNews(wmNews);
    }

    @Autowired
    private WmSensitiveService wmSensitiveService;
    /**
     * 敏感词检测
     * @param text
     * @param wmNewsId
     * @return
     */
    private boolean handlerSensitiveScan(String text, Integer wmNewsId) {
        List<WmSensitive> list = wmSensitiveService.list();

        List<String> sensitiveWords = list.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());

        Map<String, Integer> map = SensitiveWordUtil.matchWords(sensitiveWords, text);

        if(!CollectionUtils.isEmpty(map)){
            log.info("内容包含敏感词。map={}",map);
            String reason = "";
            for (String key : map.keySet()) {
                if(reason.length()>0){
                    reason += ",";
                }
                reason += key;
            }
//            修改自媒体文章状态
            updateWmNewsStatus(wmNewsId,2,reason,null);
            return false;
        }

        return true;
    }

    @Autowired
    private ArticleFeign articleFeign;
    /**
     * 远程调用发布文章
     * @param wmNews
     */
    @Override
    @GlobalTransactional
    public void pubWmNews(WmNews wmNews) {
        log.info("开始发布文章");
        WmNewsResultDTO dto = BeanHelper.copyProperties(wmNews, WmNewsResultDTO.class);
//        远程调用article服务，返回文章id
        try {
            Long articleId = articleFeign.saveArticle(dto);
//        修改自媒体文章状态 9-已发布
            updateWmNewsStatus(wmNews.getId(),9,null,articleId);
        }catch (Exception e){
            log.error("远程调用article 异常！");
            e.printStackTrace();
        }
    }

    @Autowired
    private MinioService minioService;
    @Autowired
    private GreenImageUploadScan greenImageUploadScan;
    /**
     * 阿里云接口 检测图片
     * @param imageUrls
     * @return
     */
    private boolean handlerAliyunImageScan(Set<String> imageUrls,Integer wmNewsId) {

        List<byte[]> images = new ArrayList<>();
//        从minio下载图片
        for (String imageUrl : imageUrls) {
            byte[] bytes = minioService.downLoadFile(imageUrl);
            images.add(bytes);
        }
        try {
            Map<String, String> map = greenImageUploadScan.imageScan(images);
            if(CollectionUtils.isEmpty(map)){
                log.error("调用阿里云图片审核接口异常");
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
            }
            String suggestion = map.get("suggestion");
            String label = map.get("label");
            if(StringUtils.isBlank(suggestion)){
                log.error("调用阿里云图片审核接口异常");
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
            }
            if("pass".equals(suggestion)){
                log.info("######图片审核通过");
                return true;
            }else if("review".equals(suggestion)){
//                需要人工审核
                log.info("阿里云图片审核接口，需要人工审核");
//                修改自媒体文章表status 3 -待人工审核
                updateWmNewsStatus(wmNewsId,3,label,null);
                return false;
            }else{
//                审核不通过
                log.info("阿里云图片审核接口，不通过");
//                修改自媒体文章表status 2-审核不通过
                updateWmNewsStatus(wmNewsId,2,label,null);
                return  false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }

    }


    @Autowired
    private GreenTextScan greenTextScan;
    /**
     * 阿里云文本检测
     * @param text
     * @return
     */
    private boolean handlerAliyunTextScan(String text,Integer wmNewsId) {
        try {
            Map<String, String> map = greenTextScan.greenTextScan(text);
            if(CollectionUtils.isEmpty(map)){
                log.error("调用阿里云文本审核接口异常");
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
            }
            String suggestion = map.get("suggestion");
            String reason = map.get("reason");
            if(StringUtils.isBlank(suggestion)){
                log.error("调用阿里云文本审核接口异常");
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
            }
            if("pass".equals(suggestion)){
                log.info("######文本审核通过");
                return true;
            }else if("review".equals(suggestion)){
//                需要人工审核
                log.info("阿里云文本审核接口，需要人工审核");
//                修改自媒体文章表status 3 -待人工审核
                updateWmNewsStatus(wmNewsId,3,reason,null);
                return false;
            }else{
//                审核不通过
                log.info("阿里云文本审核接口，不通过");
//                修改自媒体文章表status 2-审核不通过
                updateWmNewsStatus(wmNewsId,2,reason,null);
                return  false;
            }
        } catch (Exception e) {
            log.error("阿里云文本审核异常");
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
    }

    /**
     * 获取自媒体文章文本和图片路径
     * @param wmNews
     * @return
     */
    private Map<String, Object> handlerGetTextAndImageUrl(WmNews wmNews) {
        Map<String, Object> map = new HashMap<>();
//        存放所有的文本内容
        StringBuilder sbr = new StringBuilder();
//        存放所有的图片路径，去重
        Set<String> imageUrls = new HashSet<>();
//        标题
        String title = wmNews.getTitle();
        sbr.append(title);
//        文章内容，包含图片和文本
        String content = wmNews.getContent();

        List<Map<String,Object>> list = JsonUtils.nativeRead(content, new TypeReference<List<Map<String, Object>>>() {});
        for (Map<String, Object> m : list) {
            String type = m.get("type").toString();
            if("text".equals(type)){
//                获取文本内容
                sbr.append(",").append(m.get("value"));
            }else{
//                获取图片
                imageUrls.add(m.get("value").toString());
            }
        }
//        处理封面
        if(StringUtils.isNotBlank(wmNews.getImages())){
            imageUrls.addAll(
                    Arrays.asList(wmNews.getImages().split(",")));
        }
        map.put("text",sbr.toString());
        map.put("image",imageUrls);
        return map;
    }

    /**
     * 更新自媒体文章状态
     * @param wmNewsId
     * @param status
     */
    private void updateWmNewsStatus(Integer wmNewsId, int status,String reason,Long articleId) {
        WmNews wmNews = new WmNews();
        wmNews.setId(wmNewsId);
        wmNews.setStatus(status);
        if(StringUtils.isNotBlank(reason)) {
//            审核不同过原因
            wmNews.setReason(reason);
        }
        if(articleId != null){
            wmNews.setArticleId(articleId);
        }
        wmNewsService.updateById(wmNews);
    }
}
